package lucene;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class fileManager implements IndexingProxy, Serializable {
    
    public ArrayList<StoredFile> watchlist;
    public StoredFile cfile;
    
    fileManager()
    {
        //check daca exista obiect serializat intr-un folder dat
        //if/else serializeaza sau new obj
        watchlist = new ArrayList<>();
        this.cfile = null;
    }

    /*
    Adaugarea unui nou fisier spre indexare si inregistrare in aplicatie
    */
    @Override
    public void addFile(File file, String originalPath, String newPath) throws IOException {
        if(!file.isDirectory())
        {
            boolean found = false;
            //verifica daca exista in watchlist
            for(int i = 0; i < watchlist.size(); i++)
            {/*
                if(watchlist.get(i).getName().equals(file.getName()))
                {
                    found = true;
                    try {
                        if(watchlist.get(i).heavilyModified())
                        {
                           watchlist.get(i).CreateIndex(originalPath,newPath + "_diff");
                        }
                    } catch (IOException ex) {
                        Logger.getLogger(fileManager.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    break;
                }
                */
            }
            if(!found)
            {
                //creating a new index and storage for the file
                StoredFile fil = new StoredFile(file,originalPath);
                watchlist.add(fil);
                try {
                    fil.CreateIndex(originalPath,newPath);
                } catch (IOException ex) {
                    Logger.getLogger(fileManager.class.getName()).log(Level.SEVERE, null, ex);
                }
                
                System.out.println("*******************");
                System.out.println(originalPath.toString());
                System.out.println(file.toString());
                System.out.println(newPath.toString());
                System.out.println("*******************");
                
                archive(newPath.toString(),1);
            
            }
        }  
        else
        {
            System.out.println("Err");
        }
    }

    /*
    Stergerea unui fisier indexat impreuna cu toate fisierele asociate acestuia
    */
    @Override
    public void removeFile(File file) {
    	System.out.println(file.getName());
        //remove din watchlist
        for(int i = 0; i < watchlist.size(); i++)
        {
        	System.out.println(watchlist.get(i).getName());
            if(watchlist.get(i).getName().equals(file.getName()))
            {
            	/*
                for(int j=1;j<=watchlist.get(i).getCounter();j++) {
                	File f = new File("Monitor\\Resource-"+watchlist.get(i).getName()+"\\"+j+"\\"+watchlist.get(i).getName());
                	System.out.println("cale e "+f.toString());
                	f.delete();	
                }
                */
            	watchlist.remove(watchlist.get(i));
                System.out.println("remove");
            }
        }
        //se sterge arhiva asociata impreuna cu fisierul 
    }

    /*
    La alegerea unei versiuni vechi spre a fi vizualizata se apeleaza metoda si
    incepe procesul de highlighting a contentului
    */
    @Override
    public void selectDisplayVersion(String version) {
        cfile.setVersion(version);
    }

    /*
    Returneaza lista de versiuni spre afisare la modulul de interfata
    */
    @Override
    public ArrayList<String> getVersionList() {
        return cfile.versionList();
    }

    /*
    Apelat cand se alege fisierul pentru display
    */
    @Override
    public void selectCurrentFile(File file) {
        for(int i = 0; i < watchlist.size(); i++)
        {
            if(watchlist.get(i).getName().equals(file.getName()))
            {
                this.cfile.resetFile(watchlist.get(i));
            }
            //resets the current selected file
        }
    }
    
    
    public void archive(String path,int nr) throws IOException {
    	path = path + "\\" + Integer.toString(nr);
    	ZipOutputStream out = new ZipOutputStream(new FileOutputStream(path + "\\" + Integer.toString(nr) + ".zip"));
    	File directory = new File(path);
    	//list all the directory contents
 	    String files[] = directory.list();
 	    String end;
 	    for(int i=0; i<files.length; i++) {
 	    	end = files[i].substring(files[i].length()-3,files[i].length());
 	    	if((!end.equals("zip")) && (!end.equals("txt"))) {
	 	    	//System.out.println("-----" + files[i]);
	 	    	FileInputStream in = new FileInputStream(path + "\\" + files[i]);
	 	    	out.putNextEntry(new ZipEntry(files[i]));
	 	    	byte[] b = new byte[1024];
	 	        int count;
	 	        while ((count = in.read(b)) > 0) {
	 	            //System.out.println();
	 	            out.write(b, 0, count);
	 	        }
	 	        //out.close();
	 	        in.close();
 	    	}
        }
 	    out.close();
 	    File[] Files = directory.listFiles();
	    for(int i=0; i<files.length; i++) {
	    	end = files[i].substring(files[i].length()-3,files[i].length());
	    	//System.out.println("*****" + end);
	    	if((!end.equals("zip")) && (!end.equals("txt"))) {
	    		//File deletion = new File(files[i]);
	    		Files[i].delete();
	    	}
	    }
    }
    
    
    public void dearchive(String filename) {
    	//String filename = "C:\\Users\\LG\\Desktop\\IP archive\\arc.zip";
    	filename = filename + "\\" + filename.substring(filename.lastIndexOf("\\"),filename.length()) + ".zip";
        File srcFile = new File(filename);
        // create a directory with the same name to which the contents will be extracted
        String zipPath = filename.substring(0, filename.lastIndexOf("\\"));
        //File temp = new File(zipPath);
        //temp.mkdir();
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            // get an enumeration of the ZIP file entries
            Enumeration<ZipEntry> e = (Enumeration<ZipEntry>) zipFile.entries();
            while (e.hasMoreElements()) {
                ZipEntry entry = e.nextElement();
                //System.out.println("Entry: " + e.nextElement().getName());
                File destinationPath = new File(zipPath, entry.getName());
                System.out.println("Path-ul: " + zipPath);
                System.out.println("Numele: " + entry.getName());

                //create parent directories
                destinationPath.getParentFile().mkdirs();
                // if the entry is a file extract it
                if (entry.isDirectory()) {
                    continue;
                }
                else {
                    System.out.println("Extracting file: " + destinationPath);
                    BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
                    int b;
                    byte buffer[] = new byte[1024];
                    FileOutputStream fos = new FileOutputStream(destinationPath);
                    BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);
                    while ((b = bis.read(buffer, 0, 1024)) != -1) {
                        bos.write(buffer, 0, b);
                    }
                    bos.close();
                    bis.close();
                }
                 
            }
        }
        catch (IOException ioe) {
            System.out.println("Error opening zip file" + ioe);
        }
         finally {
             try {
                 if (zipFile!=null) {
                     zipFile.close();
                 }
             }
             catch (IOException ioe) {
                    System.out.println("Error while closing zip file" + ioe);
             }
         }
    }
    
    private void copy(InputStream from, OutputStream to) throws IOException {
        byte[] buffer = new byte[4096];
        while (true) {
            int numBytes = from.read(buffer);
            if (numBytes == -1) {
                break;
            }
            to.write(buffer, 0, numBytes);
        }
    }
    
    @Override
    public void checkFiles() throws IOException
    {
    	
    	System.out.println(watchlist.size());
        for(int i = 0; i < watchlist.size(); i++)
        {
        	System.out.println(watchlist.get(i).getData().toString());
        	System.out.println(watchlist.get(i).getData().toString().substring(0,watchlist.get(i).getData().toString().lastIndexOf("\\")) + "\\" + watchlist.get(i).getVersion() + watchlist.get(i).getData().toString().substring(watchlist.get(i).getData().toString().lastIndexOf("\\"),watchlist.get(i).getData().toString().length()));
			String deArc;
			//deArc = 
			for(int j=1;j<=Integer.parseInt(watchlist.get(i).getVersion());j++) {
				deArc = watchlist.get(i).getData().toString().substring(0,watchlist.get(i).getData().toString().lastIndexOf("\\")) + "\\" + Integer.toString(j);
				System.out.println("-*-*-*-" + deArc);
				dearchive(deArc);
			}
			
			if(watchlist.get(i).getData().toString().substring(watchlist.get(i).getData().toString().lastIndexOf(".")+1, watchlist.get(i).getData().toString().length()).equals("html")){
				OutputStream out = new FileOutputStream(watchlist.get(i).getData().toString());

		        URL url = new URL(watchlist.get(i).getDiskPath());
		        URLConnection conn = url.openConnection();
		        conn.connect();
		        InputStream is = conn.getInputStream();

		        copy(is, out);
		        is.close();
		        out.close();
			} else {
	        	InputStream inStream = null;
				OutputStream outStream = null;
	        	File source = new File(watchlist.get(i).getDiskPath());
				File destination = new File(watchlist.get(i).getData().toString());
	
				inStream = new FileInputStream(source);
				outStream = new FileOutputStream(destination);
				int length;
				byte[] buffer = new byte[1024];
				while((length = inStream.read(buffer)) > 0) {
					outStream.write(buffer,0,length);
				}				
				inStream.close();
				outStream.close();
			}
			
			watchlist.get(i).addVersion();
			watchlist.get(i).CreateIndex(watchlist.get(i).getData().toString(), watchlist.get(i).getData().toString().substring(0, watchlist.get(i).getData().toString().lastIndexOf("\\")));
			
			if(watchlist.get(i).heavilyModified()) {
				watchlist.get(i).removeVersion();
				
				System.out.println("-------------------------");
				System.out.println(watchlist.get(i).getData().toString().substring(0,watchlist.get(i).getData().toString().lastIndexOf("\\")) + "\\" + watchlist.get(i).getVersion() + watchlist.get(i).getData().toString().substring(watchlist.get(i).getData().toString().lastIndexOf("\\"),watchlist.get(i).getData().toString().length()));
				System.out.println("-------------------------");
				
				
				InputStream innStream = null;
				OutputStream outtStream = null;
	        	File ssource = new File(watchlist.get(i).getData().toString().substring(0,watchlist.get(i).getData().toString().lastIndexOf("\\")) + "\\" + watchlist.get(i).getVersion() + watchlist.get(i).getData().toString().substring(watchlist.get(i).getData().toString().lastIndexOf("\\"),watchlist.get(i).getData().toString().length()));
				File ddestination = new File(watchlist.get(i).getData().toString());

				innStream = new FileInputStream(ssource);
				outtStream = new FileOutputStream(ddestination);
				int length1;
				byte[] buffer1 = new byte[1024];
				while((length1 = innStream.read(buffer1)) > 0) {
					outtStream.write(buffer1,0,length1);
				}				
				innStream.close();
				outtStream.close();
				
				
				
			} else {
				for(int k=1; k<Integer.parseInt(watchlist.get(i).getVersion());k++) {
					watchlist.get(i).updateLists(k);
				}
			}
			for(int j=1;j<=Integer.parseInt(watchlist.get(i).getVersion());j++) {
				deArc = watchlist.get(i).getData().toString().substring(0,watchlist.get(i).getData().toString().lastIndexOf("\\"));
				archive(deArc,j);
			}
			
        }
    }
    
    private void printname()
    {
        System.out.println(watchlist.get(0).getName());
    }
    
}